<?php

declare(strict_types=1);

namespace App\Services;

use PDO;

final class Auth
{
    private const SESSION_USER_KEY = '_auth_user';

    public static function user(): ?array
    {
        if (session_status() !== \PHP_SESSION_ACTIVE) {
            session_start();
        }
        $u = $_SESSION[self::SESSION_USER_KEY] ?? null;
        return is_array($u) ? $u : null;
    }

    public static function check(): bool
    {
        return self::user() !== null;
    }

    public static function logout(): void
    {
        if (session_status() !== \PHP_SESSION_ACTIVE) {
            session_start();
        }
        unset($_SESSION[self::SESSION_USER_KEY]);
    }

    public static function attempt(string $identity, string $password): bool
    {
        $identity = trim($identity);
        $pdo = Database::pdo();
        self::ensureUsersTable($pdo);

        $stmt = $pdo->prepare("SELECT id, username, email, password_hash FROM users WHERE username = :id1 OR email = :id2 LIMIT 1");
        $stmt->execute([':id1' => $identity, ':id2' => $identity]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$row) {
            return false;
        }
        if (!password_verify($password, (string)$row['password_hash'])) {
            return false;
        }
        self::login([
            'id' => (int)$row['id'],
            'username' => (string)$row['username'],
            'email' => (string)$row['email'],
        ]);
        return true;
    }

    public static function login(array $user): void
    {
        if (session_status() !== \PHP_SESSION_ACTIVE) {
            session_start();
        }
        $_SESSION[self::SESSION_USER_KEY] = [
            'id' => (int)($user['id'] ?? 0),
            'username' => (string)($user['username'] ?? ''),
            'email' => (string)($user['email'] ?? ''),
        ];
    }

    public static function register(string $username, string $email, string $password): array
    {
        $pdo = Database::pdo();
        self::ensureUsersTable($pdo);

        // 唯一性检查
        $check = $pdo->prepare("SELECT username, email FROM users WHERE username = :u OR email = :e LIMIT 1");
        $check->execute([':u' => $username, ':e' => $email]);
        if ($row = $check->fetch(PDO::FETCH_ASSOC)) {
            if (strcasecmp((string)$row['username'], $username) === 0) {
                throw new \RuntimeException('用户名已存在');
            }
            if (strcasecmp((string)$row['email'], $email) === 0) {
                throw new \RuntimeException('邮箱已存在');
            }
        }

        $hash = password_hash($password, PASSWORD_DEFAULT);
        $ins = $pdo->prepare("INSERT INTO users (username, email, password_hash) VALUES (:u, :e, :p)");
        $ins->execute([':u' => $username, ':e' => $email, ':p' => $hash]);

        $id = (int)$pdo->lastInsertId();
        $user = ['id' => $id, 'username' => $username, 'email' => $email];
        self::login($user);
        return $user;
    }

    public static function ensureUsersTable(PDO $pdo): void
    {
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS users (
              id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              username VARCHAR(50) NOT NULL UNIQUE,
              email VARCHAR(120) NOT NULL UNIQUE,
              password_hash VARCHAR(255) NOT NULL,
              created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
        ");
    }
}
